package com.wen.bean;

import javax.swing.*;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @Description:
 * @Author: wenxin
 * @Date: 2022/7/11 14:48
 * @Version: 1.0
 */
public class DigitalText extends JTextField implements Serializable {

    /**
     * 用来输入正整数的单行文本框 可以控制输入的最大长度，最大值和最小值并在显示时可以选择是否在数字前面补零以达到最大长度
     */
    private static final long serialVersionUID = 1L;
    /** 数据成员变量，分别代表当前值，最大值，最小值和最大长度,分别赋默认值 */
    private int value = 0;
    private int maxValue = 99;
    private int minValue = 0;
    private int maxLength = 2;
    /** 成员变量，代表输入框是否需要在最前面补零，true表示需要 */
    private boolean enableAddZero = false;

    // 构造函数
    public DigitalText() {
        try {
            initGUI();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initGUI() throws Exception {
        setDocument(new DigitalTextDocument());
        setHorizontalAlignment(JTextField.RIGHT);

        setMaxLength(maxLength = 2);
        setMaxValue(maxValue = 99);
        setMinValue(minValue = 0);

        addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                this_keyReleased(e);
            }
        });
        addFocusListener(new java.awt.event.FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                // this_focusLost(e); //失去焦点时不做任何事，这样比较符合Windows的习惯
            }

            @Override
            public void focusGained(FocusEvent e) {
                // this_focusGained(e); //得到焦点时不做任何事，这样比较符合Windows的习惯
            }
        });
    }

    public void setValue(int newValue) {
        if ((newValue <= maxValue) && (newValue >= minValue)) {
            value = newValue;
        }
        setText(Integer.toString(value));
        adjustForZero();
        revalidate();
    }

    // 获取value
    public int getValue() {
        return Integer.parseInt(this.getText());
    }

    // 设置最大值
    public void setMaxValue(int maxValue) {
        setMinMaxValue(minValue, maxValue);
    }

    // 获取最大值
    public int getMaxValue() {
        return maxValue;
    }

    // 设置最小值
    public void setMinValue(int minValue) {
        setMinMaxValue(minValue, maxValue);
    }

    // 获取最小值
    public int getMinValue() {
        return minValue;
    }

    public void setMinMaxValue(int minValue, int maxValue) {
        int tempMinValue = minValue;
        int tempMaxValue = maxValue;

        if (tempMinValue > tempMaxValue) {
            return;
        }

        if (tempMaxValue < 0
                || tempMinValue > (int) Math.pow(10, maxLength) - 1) {
            return;
        }

        if (tempMinValue < 0) {
            tempMinValue = 0;
        }

        if (tempMaxValue > (int) Math.pow(10, maxLength) - 1) {
            tempMaxValue = (int) Math.pow(10, maxLength) - 1;
        }

        this.maxValue = tempMaxValue;
        this.minValue = tempMinValue;

        if (value < minValue) {
            setValue(minValue);
        }

        if (value > maxValue) {
            setValue(maxValue);
        }

        ((DigitalTextDocument) getDocument()).setMinValue(minValue);
        ((DigitalTextDocument) getDocument()).setMaxValue(maxValue);
    }

    public void setMaxLength(int newMaxLength) {
        if (newMaxLength < 1) {
            return;
        }

        if (newMaxLength >= maxLength) {
            this.maxLength = newMaxLength;
            ((DigitalTextDocument) getDocument()).setMaxLength(maxLength);
        } else {
            if (minValue > (int) Math.pow(10, newMaxLength) - 1) {
                setMinMaxValue(0, (int) Math.pow(10, newMaxLength) - 1);
            } else if (maxValue > (int) Math.pow(10, newMaxLength) - 1) {
                setMinMaxValue(minValue,
                        (int) Math.pow(10, newMaxLength) - 1);
            }
            maxLength = newMaxLength;
            ((DigitalTextDocument) getDocument()).setMaxLength(maxLength);
        }
    }

    public int getMaxLength() {
        return maxLength;
    }

    private void this_focusLost(FocusEvent e) {
        commit();
    }

    void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
    }

    void readObject(ObjectInputStream ois) throws ClassNotFoundException,
            IOException {
        ois.defaultReadObject();
    }

    public void adjustForZero() {
        if (enableAddZero) {
            String tempStr = Integer.toString(getValue());
            int addZeroNumber = maxLength - tempStr.length();
            for (int i = 0; i < addZeroNumber; i++) {
                tempStr = "0" + tempStr;
            }
            setText(tempStr);
            revalidate();
        } else {
            int tempValue = Integer.parseInt(getText().trim());
            setText(Integer.toString(tempValue));
            revalidate();
        }
    }

    public void setEnableAddZero(boolean newEnableAddZero) {
        enableAddZero = newEnableAddZero;
        adjustForZero();
    }

    public boolean isEnableAddZero() {
        return enableAddZero;
    }

    void this_keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            commit();
        }
        if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            setValue(value);
        }
    }

    private void commit() {
        try {
            setValue(Integer.parseInt(getText()));
        } catch (Exception ex) {
            setValue(value);
            return;
        }
    }

    void this_focusGained(FocusEvent e) {
        this.selectAll();
    }
}
